import wx
from PIL import Image


class PreviewPanel(wx.Panel):
    source_image: wx.Image
    view_image: wx.Image

    def __init__(self, parent=None):
        super().__init__(parent)
        self.SetWindowStyle(wx.BORDER_SUNKEN)

        self.Bind(wx.EVT_PAINT, self.__paint)

    def clear_image(self):
        if hasattr(self, "source_image"):
            self.source_image.Destroy()
            del self.source_image
        if hasattr(self, "view_image"):
            self.view_image.Destroy()
            del self.view_image
        self.Refresh()

    def load_pil_image(self, image: Image):
        self.clear_image()
        self.source_image = wx.Image(*image.size, clear=False)
        if image.mode[-1] == "A":
            image_data_with_alpha = image.copy()
            self.source_image.SetData(image_data_with_alpha.convert("RGB").tobytes())
            self.source_image.SetAlpha(image_data_with_alpha.tobytes()[3::4])
        else:
            image_data = image.copy()
            self.source_image.SetData(image_data.convert("RGB").tobytes())
        self.Refresh()

    def load_image(self, path: str = ""):
        self.clear_image()
        if len(path) > 0:
            self.source_image = wx.Image(path, type=wx.BITMAP_TYPE_ANY)
        self.Refresh()

    def _calculate_scale(self):
        panel_size = self.GetSize()
        source_size = self.source_image.GetSize()
        source_ratio = source_size.GetWidth() / source_size.GetHeight()
        panel_ratio = panel_size.GetWidth() / panel_size.GetHeight()
        if source_ratio >= panel_ratio:
            scale_width = panel_size.GetWidth()
            scale_height = scale_width / source_ratio
        else:
            scale_height = panel_size.GetHeight()
            scale_width = scale_height * source_ratio
        return round(scale_width), round(scale_height)

    def __paint(self, _):
        dc = wx.PaintDC(self)
        dc.SetBackground(wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)))
        dc.Clear()

        if hasattr(self, "source_image"):
            panel_size = self.GetSize()
            if not hasattr(self, "view_image"):
                scale_width, scale_height = self._calculate_scale()
                self.view_image = self.source_image.Scale(scale_width,
                                                          scale_height,
                                                          wx.IMAGE_QUALITY_HIGH)
            view_image_size = self.view_image.GetSize()
            if view_image_size.GetHeight() == panel_size.GetHeight() or \
                    view_image_size.GetWidth() == panel_size.GetWidth():
                dc.DrawBitmap(self.view_image.ConvertToBitmap(),
                              (panel_size.GetWidth() - view_image_size.GetWidth()) // 2,
                              (panel_size.GetHeight() - view_image_size.GetHeight()) // 2)
